package com.chucang.shucang.pms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chucang.shucang.common.base.constant.SecurityConstant;
import com.chucang.shucang.common.base.exception.FastException;
import com.chucang.shucang.common.base.page.PageData;
import com.chucang.shucang.common.base.page.PageQuery;
import com.chucang.shucang.common.base.redis.RedisUtil;
import com.chucang.shucang.common.base.redis.vo.PanicPurchaseProductRedisVO;
import com.chucang.shucang.common.base.service.impl.CrudServiceImpl;
import com.chucang.shucang.common.base.utils.CaffeineUtil;
import com.chucang.shucang.common.base.utils.OpsUtil;
import com.chucang.shucang.common.base.utils.R;
import com.chucang.shucang.pms.constant.PmsCacheConstant;
import com.chucang.shucang.pms.constant.PmsCommonConstant;
import com.chucang.shucang.pms.dao.CollectionBaseDao;
import com.chucang.shucang.pms.dto.CollectionBaseDTO;
import com.chucang.shucang.pms.entity.CollectionBaseEntity;
import com.chucang.shucang.pms.feign.UserService;
import com.chucang.shucang.pms.feign.vo.UserBaseEntity;
import com.chucang.shucang.pms.service.CollectionBaseService;
import com.chucang.shucang.pms.vo.CollectionBasePageResVO;
import com.chucang.shucang.pms.vo.CollectionDetailResVO;
import com.chucang.shucang.pms.vo.query.CollectionBaseQuery;
import com.chucang.shucang.pms.vo.query.CollectionMallQuery;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * 藏品基础信息和发售表
 *
 * @author flitsneak flitsneak@gmail.com
 * @since 1.0.0 2022-09-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CollectionBaseServiceImpl extends CrudServiceImpl<CollectionBaseDao, CollectionBaseEntity, CollectionBaseDTO> implements CollectionBaseService {

    private final UserService userService;
    private final RedisUtil redisUtil;
    private final CaffeineUtil caffeineUtil;

    private static final int SOLD_OUT = 2;
    private static final int ON_SELL = 1;
    private static final int PRE_SELL = 0;

    @Override
    @Cacheable(value = "collectionBasePage", key = "{#collectionMallQuery.page}", unless = "#collectionMallQuery.fuzzy!=null")
    public PageData<CollectionBaseEntity> collectionBasePage(CollectionMallQuery collectionMallQuery) {
        LambdaQueryWrapper<CollectionBaseEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .like(!CharSequenceUtil.isBlank(collectionMallQuery.getFuzzy()), CollectionBaseEntity::getDcName, collectionMallQuery.getFuzzy())
                .eq(CollectionBaseEntity::getDcAttribute, PmsCommonConstant.FOR_SELL)
                .eq(CollectionBaseEntity::getStatus, PmsCommonConstant.ON_SHELF)
                .select(CollectionBaseEntity::getId, CollectionBaseEntity::getDcName, CollectionBaseEntity::getCoverPicture, CollectionBaseEntity::getDcPrice)
                .orderByDesc(CollectionBaseEntity::getCreateTime);
        IPage<CollectionBaseEntity> page = this.page(
                new PageQuery<CollectionBaseEntity>().getPage(collectionMallQuery),
                lambdaQueryWrapper
        );
        return new PageData<>(page);
    }

    @Override
    public PageData<CollectionBasePageResVO> collectionsBasePage(CollectionBaseQuery collectionBaseQuery) {
        LambdaQueryWrapper<CollectionBaseEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(CollectionBaseEntity::getStatus, PmsCommonConstant.ON_SHELF)
                .eq(CollectionBaseEntity::getDcAttribute, PmsCommonConstant.FOR_SELL)
                .select()
                .orderByDesc(CollectionBaseEntity::getCreateTime);
        if (!CharSequenceUtil.isBlank(collectionBaseQuery.getS())) {
            lambdaQueryWrapper.like(CollectionBaseEntity::getDcName, collectionBaseQuery.getS());
        }
        IPage<CollectionBaseEntity> page = this.page(
                new PageQuery<CollectionBaseEntity>().getPage(collectionBaseQuery),
                lambdaQueryWrapper
        );
        if (CollUtil.isEmpty(page.getRecords())) {
            return new PageData<>(Collections.emptyList(), 0);
        }
        //收集发行人信息
        Map<Long, String> stringHashMap = new HashMap<>(32);
        Set<Long> set = new HashSet<>(16);
        page.getRecords().forEach(c ->
                set.add(c.getPublisherId())
        );
        //发行人
        R<List<UserBaseEntity>> baseInfo = userService.listUserBaseInfo(set, SecurityConstant.FROM_IN);
        List<UserBaseEntity> baseEntities = OpsUtil.of(baseInfo)
                .assertDataNotNull(e -> new FastException("查询用户信息异常"))
                .getData()
                .get();
        baseEntities.forEach(d ->
                stringHashMap.put(d.getId(), d.getUsername())
        );
        List<CollectionBasePageResVO> basePageResVOS = BeanUtil.copyToList(page.getRecords(), CollectionBasePageResVO.class);
        basePageResVOS.forEach(b -> {
            b.setUsername(stringHashMap.get(b.getPublisherId()));
            long begin = b.getStartTime().getTime();
            long end = b.getEndTime().getTime();
            long now = new Date().getTime();
            if (begin < now && now < end) {
                if (Objects.nonNull(caffeineUtil.getObject("sw" + b.getId()))) {
                    b.setStatus(SOLD_OUT);
                } else {
                    long surplus = redisUtil.getListSize(String.format(PmsCacheConstant.COLLECTION_SERIAL_NUMS, b.getId()));
                    if (surplus <= 0) {
                        b.setStatus(SOLD_OUT);
                        caffeineUtil.setValue("sw" + b.getId(), SOLD_OUT);
                    } else {
                        b.setStatus(ON_SELL);
                    }
                }
            } else if (now < begin) {
                b.setStatus(PRE_SELL);
            } else if (now > end) {
                b.setStatus(SOLD_OUT);
            }
        });
        return new PageData<>(basePageResVOS, page.getTotal());
    }

    @Override
    public CollectionDetailResVO getCollectionDetail(Long id) {
        //在售信息
        CollectionBaseEntity byId = this.getById(id);

        CollectionDetailResVO collectionDetailResVO = new CollectionDetailResVO();
        BeanUtil.copyProperties(byId, collectionDetailResVO);
        long begin = byId.getStartTime().getTime();
        long end = byId.getEndTime().getTime();
        long now = new Date().getTime();
        if (begin < now && now < end) {
            if (Objects.nonNull(caffeineUtil.getObject("sw" + byId.getId()))) {
                collectionDetailResVO.setStatus(SOLD_OUT);
            } else {
                long surplus = redisUtil.getListSize(String.format(PmsCacheConstant.COLLECTION_SERIAL_NUMS, byId.getId()));
                if (surplus <= 0) {
                    collectionDetailResVO.setStatus(SOLD_OUT);
                    caffeineUtil.setValue("sw" + byId.getId(), SOLD_OUT);
                    caffeineUtil.remove(byId.getId().toString());
                    caffeineUtil.remove("xg" + byId.getId());
                } else {
                    collectionDetailResVO.setStatus(ON_SELL);
                    //正在销售，插入秒杀信息
                    if (Objects.isNull(caffeineUtil.getObject(byId.getId().toString()))) {
                        Object redisVO = redisUtil.getHashValue(PmsCacheConstant.PRE_ON_SELL_DETAILS, String.format(PmsCacheConstant.COLLECTION_ON_SHELVE, byId.getId(), begin, end));
                        log.info("查询缓存值：{}", String.format(PmsCacheConstant.COLLECTION_ON_SHELVE, byId.getId(), begin, end));
                        if (Objects.nonNull(redisVO)) {
                            String token = ((PanicPurchaseProductRedisVO) redisVO).getToken();
                            Integer perLimit = ((PanicPurchaseProductRedisVO) redisVO).getPerLimit();
                            collectionDetailResVO.setPurchaseKey(token);
                            caffeineUtil.setValue(byId.getId().toString(), token);
                            caffeineUtil.setValue("xg" + byId.getId(), perLimit);
                        }
                    } else {
                        log.info("collection---caffeine");
                        collectionDetailResVO.setPurchaseKey((String) caffeineUtil.getObject(byId.getId().toString()));
                        collectionDetailResVO.setPerLimit((Integer) caffeineUtil.getObject("xg" + byId.getId()));
                    }
                }
            }
        } else if (now < begin) {
            collectionDetailResVO.setStatus(PRE_SELL);
        } else if (now > end) {
            collectionDetailResVO.setStatus(SOLD_OUT);
        }
        //账号信息
        R<UserBaseEntity> baseInfoById = userService.getUserBaseInfoById(byId.getPublisherId(), SecurityConstant.FROM_IN);
        UserBaseEntity userBaseEntity = OpsUtil
                .of(baseInfoById)
                .assertDataNotNull(e -> new FastException("获取用户信息失败"))
                .getData()
                .get();

        collectionDetailResVO.setUsername(userBaseEntity.getUsername());
        collectionDetailResVO.setOffshoreAccount(userBaseEntity.getOffshoreAccount());
        collectionDetailResVO.setAccountType(userBaseEntity.getAccountType());

        return collectionDetailResVO;
    }
}